package com.jbp.aspect;

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.jbp.exception.RRException;
import com.jbp.service.PropertyService;
import com.jbp.utils.encryptUtils.RsaEncryptUtil;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.stereotype.Component;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;

/**
 * 这里实现了HttpInputMessage，封装一个解密RSA请求体的DecryptInputMessage
 */
class DecryptInputMessageRSA implements HttpInputMessage {
    private static final Logger logger = LoggerFactory.getLogger(DecryptInputMessageRSA.class);

    private HttpHeaders headers;
    private InputStream body;
    private PropertyService propertyService;

    public DecryptInputMessageRSA(HttpInputMessage httpInputMessage, PropertyService propertyService) throws IOException {
        this.headers = httpInputMessage.getHeaders();
        this.propertyService = propertyService;
        this.body = decrypt(httpInputMessage.getBody());
    }

    private InputStream decrypt(InputStream body) throws IOException {
        StringWriter writer = new StringWriter();
        IOUtils.copy(body, writer, StandardCharsets.UTF_8.name());
        String jsonStr = writer.toString();
        Gson gson = new Gson();
        JsonElement element = gson.fromJson (jsonStr, JsonElement.class);
        JsonObject jsonObj = element.getAsJsonObject();
        JsonElement data = jsonObj.get("data");
        if (data==null) {
            throw new RRException("请求格式错误");
        }
        String encryptedData = data.getAsString();

        long beforeDecrypt = System.currentTimeMillis();
        String privateKey = propertyService.getV("encrypt_private_key");
        String decryptedData = RsaEncryptUtil.decrypt(encryptedData, privateKey);
        long afterDecrypt = System.currentTimeMillis();
        //logger.info(String.format("decrypted data: %s", decryptedData));
        //logger.info(String.format("decrypt costs: %s", (afterDecrypt-beforeDecrypt)));
        InputStream stream = new ByteArrayInputStream(decryptedData.getBytes(StandardCharsets.UTF_8));
        return stream;
    }

    @Override
    public InputStream getBody() {
        return body;
    }

    @Override
    public HttpHeaders getHeaders() {
        return headers;
    }
}

